package infos

import (
	"time"

	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/internal/json"

	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/app/sysparam"

	"github.com/gin-gonic/gin"
	"github.com/pkg/errors"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/app/ginsrv/api/base"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/core"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/core/columnd"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/core/common"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/core/groupd"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/core/infod"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/core/interactiond"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/core/orgd"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/evt/userclievt"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/log"
)

type respInfo struct {
	InfoID      string                 `json:"info_id"` // 信息编码
	Seq         string                 `json:"page_id"` // 序列,如果存在用这个字段作为分页的pageID
	ColumnName  string                 `json:"column_name"`
	ColumnID    string                 `json:"column_id"`           // 所属栏目
	Owner       string                 `json:"owner"`               // 所有者
	Org         string                 `json:"org"`                 // 所属组织
	Kind        int                    `json:"kind"`                // 类型 1.文章，2短文，3投票，活动，调查问卷
	Title       string                 `json:"title"`               // 标题
	SubTitle    string                 `json:"sub_title"`           // 副标题标题
	ListMode    int                    `json:"list_mode"`           // 列表展示时的默认模式
	Icon        []string               `json:"icon"`                // 图标
	Banner      string                 `json:"banner"`              // 旗帜
	Desc        string                 `json:"desc"`                // 简介
	Tags        []string               `json:"tags"`                // 标签列表
	From        string                 `json:"from"`                // 来源
	Content     string                 `json:"content,omitempty"`   // 信息内容
	PublishTime time.Time              `json:"publish_time"`        // 发布时间
	Creator     string                 `json:"creator"`             // 创建人
	Extras      map[string]interface{} `json:"extras"`              //扩展信息
	CtlParam    *infoCtrlParam         `json:"ctl_param,omitempty"` // 控制参数
	URL         string                 `json:"url,omitempty"`
	Totals      infoTotal              `json:"totals"`
	My          my                     `json:"my"`
}

type infoTotal struct {
	ReplayNum int `json:"replay_num,omitempty"`
	LikeNum   int `json:"like_num,omitempty"`
	CollNum   int `json:"coll_num,omitempty"`
}

// type infoCtrlParam struct {
// 	IsReply      int      `json:"is_reply"`       // 是否开启信息评论 0 不开启 1 开启
// 	AllowIntCode []string `json:"allow_int_code"` // 允许的互动模式 对应InteractionTypeDesc中的Code
// 	IsShare      int      `json:"is_share"`       // 是否开启分享 0 不开启 1 开启
// 	IsCollect    int      `json:"is_collect"`     // 是否开启收藏  0 不开启 1 开启
// 	MyLike       int      `json:"my_like"`        // 是否我已经点赞  0 否 1 是
// 	MyColl       int      `json:"my_coll"`        // 是否我已经点赞  0 否 1 是
// }
type my struct {
	Like bool `json:"like"`
	Coll bool `json:"coll"`
}
type infoCtrlParam struct {
	IsReply int `json:"is_reply"` // 是否开启信息评论 0 不开启 1 开启
	IsShare int `json:"is_share"` // 是否开启分享 0 不开启 1 开启
	IsLike  int `json:"is_like"`
	IsColl  int `json:"is_coll"`
}

func createInfoCtrl(d core.CmsDomain) *infoCtrl {
	return &infoCtrl{
		BaseContrl: base.BaseContrl{
			Domain: d,
		},
		info: d.Info(),
		iar:  d.Info().InfoAggregateRoot(),
		car:  d.Column().ColumnAggregateRoot(),
		gar:  d.Group().GroupAggregateRoot(),
		oar:  d.Org().OrgAggregateRoot(),
		iiar: d.Interaction().InteractionAggregateRoot(),
		igar: d.Interaction().GroupAggregateRoot(),
	}
}

type infoCtrl struct {
	base.BaseContrl
	info infod.InfoDomain
	iar  infod.InfoAggregateRoot
	car  columnd.ColumnAggregateRoot
	gar  groupd.GroupAggregateRoot
	oar  orgd.OrgAggregateRoot
	iiar interactiond.InteractionAggregateRoot
	igar interactiond.GroupAggregateRoot
}

// // InfoSearch 查询条件
// type InfoSearch struct {
// 	// UID OrgID 如果都为空 :
// 	// 	 Range 0 查询所有信息包含 所有者和所属组织的信息
// 	// 	Range  1 查询除所属组织所属用户以外的信息
// 	// UID OrgID 任何一个不为空：
// 	// 	  Range 参数失效
// 	Range    int      `from:"range"`
// 	UID      string   `from:"owner"`  // 所有者用户编号
// 	OrgID    string   `from:"org"`    // 组织编号
// 	ColumnID string   `from:"column"` // 栏目编号
// 	Key      string   `from:"key"`    // 关键字
// 	Tags     []string `from:"tags"`   //  匹配标签

// }

func (c infoCtrl) geInfoSearch(ctx *gin.Context) (result infod.InfoSearch) {

	result.ColumnID = ctx.DefaultQuery("column", "")
	result.Key = ctx.DefaultQuery("key", "")
	result.OrgID = ctx.DefaultQuery("org", "")
	result.Tags, _ = ctx.GetQueryArray("tags")
	result.Range = c.GetIntByQuery(ctx, "range", 1)
	result.Status = []infod.IStatus{infod.IStatusPublished}
	if extrastr, ok := ctx.GetQuery("extral"); ok && extrastr != "" {
		if err := json.Unmarshal([]byte(extrastr), &result.Extral); err != nil {
			return
		}
	}
	return
}

// 分页获取信息列表
func (c infoCtrl) getInfoPageList(ctx *gin.Context) {

	page := c.GetPageInfo(ctx, common.PageModeID)
	dctx := c.DDDContext(ctx)
	sch := c.geInfoSearch(ctx)
	pr, cs, err := c.iar.QueryPage(dctx, sch, page)
	if err != nil {
		c.ErrServerError(ctx, 1, "查找信息列表失败", errors.Wrap(err, "查找信息列表失败"))
		return
	}
	var respInfos []interface{}
	for _, v := range cs {
		col, err1 := c.car.GetColumn(dctx, v.ColumnID)
		if err1 != nil {
			c.ErrServerError(ctx, 33, "查询文章所在栏目信息失败", errors.Wrapf(err, "查询信息(%v)所在栏目信息失败.", v.InfoID))
			err = err1
			return
		}
		respInfos = append(respInfos, adapterC2Resp(ctx, &v, col))
	}
	c.SuccessPage(ctx, page, pr, respInfos)
}

// 分页获取信息列表
func (c infoCtrl) getMyInfoPageList(ctx *gin.Context) {

	page := c.GetPageInfo(ctx, common.PageModeID)
	dctx := c.DDDContext(ctx)
	uid := dctx.UID()
	if uid == "" {
		c.ErrUnauthorized(ctx, "未登录不能访问")
		return
	}
	sch := c.geInfoSearch(ctx)
	sch.UID = uid
	pr, cs, err := c.iar.QueryPage(dctx, sch, page)
	if err != nil {
		c.ErrServerError(ctx, 1, "查找信息列表失败", errors.Wrap(err, "查找信息列表失败"))
		return
	}
	respInfos := make([]interface{}, 0, len(cs))
	for _, v := range cs {
		col, err1 := c.car.GetColumn(dctx, v.ColumnID)
		if err1 != nil {
			c.ErrServerError(ctx, 33, "查询文章所在栏目信息失败", errors.Wrapf(err, "查询信息(%v)所在栏目信息失败.", v.InfoID))
			err = err1
			return
		}
		respInfos = append(respInfos, adapterC2Resp(ctx, &v, col))
	}
	c.SuccessPage(ctx, page, pr, respInfos)
}

// 获取指定信息
func (c infoCtrl) getInfo(ctx *gin.Context) {

	infoid := ctx.Param("infoid")
	dctx := c.DDDContext(ctx)
	if infoid == "" {
		c.ErrBadRequest(ctx, 1, "请求参数错误", nil)
		return
	}
	ia, err := c.iar.GetInfo(dctx, infoid)
	if err != nil {
		c.ErrServerError(ctx, 2, "查找信息失败", errors.Wrapf(err, "检测信息(%v)是否存在失败：", infoid))
		return
	}
	if ia == nil {
		c.ErrNotFound(ctx, 3, "信息不存在", nil)
		return
	}
	if ia.Status != infod.IStatusPublished {
		c.ErrBadRequest(ctx, 1, "文章不存在或没有发布不能访问", nil)
		return
	}
	col, err := c.car.GetColumn(dctx, ia.ColumnID)
	if col == nil {
		c.ErrServerError(ctx, 1, "查询文章所在栏目信息失败", errors.Wrapf(err, "查询信息(%v)所在栏目信息失败.", infoid))
		return
	}

	icp := &infoCtrlParam{
		IsReply: col.IsReply,
		IsShare: 1,
	}

	intTypeLikeCode := sysparam.IntsLikeCode()
	intTypeCollCode := sysparam.IntsCollectionCode()
	for _, v := range col.AllowIntCode {
		switch v {
		case intTypeLikeCode:
			icp.IsLike = 1
		case intTypeCollCode:
			icp.IsColl = 1
		}
	}
	ri := &respInfo{
		InfoID:      ia.InfoID,
		ColumnID:    ia.ColumnID,
		ColumnName:  col.Name,
		Kind:        ia.Kind,
		Title:       ia.Title,
		SubTitle:    ia.SubTitle,
		ListMode:    ia.ListMode,
		Icon:        ia.Icon,
		Banner:      ia.Banner,
		From:        ia.From,
		Desc:        ia.Desc,
		Tags:        ia.Tags,
		Extras:      ia.Extras,
		PublishTime: ia.PublishTime,
		Creator:     ia.Creator,
		Content:     ia.Content,
		Owner:       ia.Owner,
		Org:         ia.Org,
		CtlParam:    icp,
	}
	uid := dctx.UID()
	if uid != "" {
		if num, err := c.iiar.QueryNum(dctx, interactiond.InteractionSearch{
			Codes: []string{intTypeLikeCode},
			IGID:  []string{c.igar.ID(interactiond.IGTTInfo, ia.InfoID)},
			UID:   []string{uid},
		}); err != nil {
			log.Warnf("查询我是否点赞失败")
		} else if num > 0 {
			ri.My.Like = true
		}
		if num, err := c.iiar.QueryNum(dctx, interactiond.InteractionSearch{
			Codes: []string{intTypeCollCode},
			IGID:  []string{c.igar.ID(interactiond.IGTTInfo, ia.InfoID)},
			UID:   []string{uid},
		}); err != nil {
			log.Warnf("查询我是否点赞失败")
		} else if num > 0 {
			ri.My.Coll = true
		}
	}
	if g, err := c.igar.GetIGroup2(dctx, interactiond.IGTTInfo, ia.InfoID); err != nil {
		log.Warnf("获取统计信息失败")
	} else if g != nil {

		ri.Totals.ReplayNum = g.ReplayNum
		for _, v := range g.GroupTotal {
			switch v.ITCode {
			case intTypeLikeCode:
				ri.Totals.LikeNum = v.Total
			case intTypeCollCode:
				ri.Totals.CollNum = v.Total
			default:
			}

		}
	}
	// 创建用户浏览信息事件
	userclievt.TriggerLookInfoEvent(ctx.Request.RequestURI, uid, interactiond.IGTTInfo, infoid)
	c.Success(ctx, ri)
}

// ReqInfoDesc 请求参数
type ReqInfoDesc struct {
	ColumnID string                 `json:"column_id" binding:"required,max=32"`
	Kind     int                    `json:"kind" binding:"required,gte=1,lte=5"`   // 类型 1.文章，2短文，3投票，4活动，5调查问卷
	Title    string                 `json:"title" binding:"required,max=100"`      // 标题
	SubTitle string                 `json:"sub_title,omitempty" binding:"max=100"` // 副标题标题
	ListMode int                    `json:"list_mode,omitempty"`                   // 列表展示时的默认模式
	Icon     []string               `json:"icon,omitempty"`                        // 图标
	Banner   string                 `json:"banner,omitempty"`                      // 封面
	From     string                 `json:"from,omitempty"`                        // 来源
	Desc     string                 `json:"desc,omitempty"`                        // 简介
	Tags     []string               `json:"tags,omitempty"`                        // 标签列表
	Content  string                 `json:"content,omitempty" binding:"max=5000"`  // 信息内容
	Extras   map[string]interface{} `json:"extras,omitempty"`                      // 扩展信息
}

// To 转换为infod.InfoDesc
func (r ReqInfoDesc) To() infod.InfoDesc {
	return infod.InfoDesc{
		ColumnID: r.ColumnID,
		Kind:     r.Kind,
		Title:    r.Title,
		SubTitle: r.SubTitle,
		ListMode: r.ListMode,
		Icon:     r.Icon,
		From:     r.From,
		Banner:   r.Banner,
		Desc:     r.Desc,
		Tags:     r.Tags,
		Content:  r.Content,
		Extras:   r.Extras,
	}
}

// ReqUpdateInfoDesc 更新请求
type ReqUpdateInfoDesc struct {
	Kind     int                    `json:"kind" binding:"required,gte=1,lte=5"`   // 类型 1.文章，2短文，3投票，4活动，5调查问卷
	Title    string                 `json:"title" binding:"required,max=100"`      // 标题
	SubTitle string                 `json:"sub_title,omitempty" binding:"max=100"` // 副标题标题
	ListMode int                    `json:"list_mode,omitempty"`                   // 列表展示时的默认模式
	Icon     []string               `json:"icon,omitempty"`                        // 图标
	Banner   string                 `json:"banner,omitempty"`                      // 封面
	From     string                 `json:"from,omitempty"`                        // 来源
	Desc     string                 `json:"desc,omitempty"`                        // 简介
	Tags     []string               `json:"tags,omitempty"`                        // 标签列表
	Content  string                 `json:"content,omitempty"`                     // 信息内容
	Extras   map[string]interface{} `json:"extras,omitempty"`                      // 扩展信息
}

// To 转换为infod.InfoDesc
func (r ReqUpdateInfoDesc) To() infod.InfoDesc {
	return infod.InfoDesc{
		Kind:     r.Kind,
		Title:    r.Title,
		SubTitle: r.SubTitle,
		ListMode: r.ListMode,
		Icon:     r.Icon,
		From:     r.From,
		Banner:   r.Banner,
		Desc:     r.Desc,
		Tags:     r.Tags,
		Content:  r.Content,
		Extras:   r.Extras,
	}
}
